Inside Airbnb

Inside Airbnb is an independent open-source data tool developed by community activist Murray Cox who aims to shed light on how Airbnb is being used and affecting neighborhoods in large cities. The tool provides a visual overview of the amount. availability, and spread of rooms across a city, an approximation of the number of bookings and occupancy rate, and the number of listings per host.

For example, here is the dashboard for the city of Amsterdam which shows us that 79% of the 19,619 listings are entire homes of which about a quarter is available all year round. Moreover, the animation below illustrates how the number of listings have been growing rapidly throughout the years:


Research Question

The overarching research question that we aim to investigate is:
How did the Airbnb market in Amsterdam respond to the COVID-19 pandemic in terms of bookings per neighborhood?

To get to an answer, we need a multitude of input, transformation, and output steps. We’ll use make to automate our workflows and make them reproducible. As data on Inside Airbnb is updated monthly, our program should still work once new data becomes available or if we change the city.


1. Input

1.1 Data

The data underlying Inside Airbnb have been analyzed, cleansed, and aggregated where appropriate to facilitate public discussion. In this data challenge, we focus on the listings.csv and reviews.csv files which contain the following information:

Listings
Information about the host, location, room type, price, reviews, and availability.

Reviews
The listing ID and the date of the review. More details about the review such as the comment and author can be reviews.csv.gz. file but is outside the scope of this tutorial.

Exercise 1
Before we fully automate our workflows, it is imperative to have a close look at the data.

  1. Set up a directory structure in accordance with these guidelines. It should have a data, gen, and src directory and a data-preparation subdirectory in src.
  2. Manually download the most recent version of listings.csv and reviews.csv listed on Inside Airbnb and store them in the data folder.
  3. Create a data report (like you did in Data Challenge 1) .
  • Code necessary to read in the data and perform some basic cleaning steps
  • Generate an overview of the data (e.g., summary statistics, report on missingness, number of observations, etc.)
  • Explore interesting relationships in the data.
listings <- read.csv("../../data/listings.csv")
summary(listings)

reviews <- read.csv("../../data/reviews.csv")
summary(reviews)


Solutions
An answer that includes:

  • The number of listings is (+/- 18K) is somewhat lower than the figure reported in the dashboard.
  • Most hosts have only one listing but some may account for 84 listings.
  • Some listings received their last review in 2012 which indicates that not all listings may be in use anymore (for 2375 records this field is empty (NA) which suggests that they did not receive a review at all. This is confirmed by the number of reviews column (0).).
  • Most listings receive less than a review per month (mean: 0.63, median: 0.30).
  • The neighborhoods with the most listings are located in De Baarsjes - Oud-West, De Pijp - Rivierenbuurt, and Centrum-West. The neighborhood_group column does not contain any information and could therefore be removed.
  • For half of the listings, the daily rate falls somewhere in between â‚Ĵ94 and â‚Ĵ180 (1st and 3rd quantile).
  • The reviews file includes all historic reviews (not just the new ones since the last data release).
  • Reviews are written between March 2009 and December 2020.
  • The total number of reviews (+/- 452K) that are grouped by listing (16K). Given the total number of listings on Airbnb, it implies that not all listings have been reviewed.

Note that the figures and years mentioned above are based on the dataset from December 2020 and thus may deviate from more recent versions of the dataset.


Exercise 2
Say that you want to share your work with others, you could essentially give them access to both the R file (src folder) and the two csv-files (data folder). Yet if you work with big data sets, you may run into problems that cannot be easily shared through email, Github, or Google Drive. For that reason, it’s recommended to create a script that pulls in the data directly from the source itself which is what you’re going to do in this exercise.

  1. Create a new file download.R and save it in the src/data-preparation folder.
  2. Look up the URL of the download links of the most recent version of the listings.csv and reviews.csv datasets.
  3. Download these two files from the aforementioned urls using the R code below and store them in the data folder. destfile in download.file() refers to the (relative) filepath and filename (e.g., ../../data/listings.csv).
download.file(url = url, destfile = filename) 
  1. Run the R script from the command line and test whether it works as expected. First, type R in the command line (e.g., Terminal on Mac) and see whether it opens the R command line. If not, you may need to configure a path to the R library as described here. Next, run the command below to run the download.R script from the terminal. It downloads the data from Inside Airbnb and stores it into the data directory.
R < download.R --save


2. Transformation

As the author of Inside Airbnb notes, guests may leave a review after their stay, and these can be used as an indicator for the number of bookings. Although only verified guests can review listings, it is unlikely that every guest will take the time to write one. In reality, the number of bookings will thus exceed the number of reviews.


Exercise 3
Think of several arguments why this may or may not be a problem in the context of our research question.

Solution
Some hosts will be more likely to get reviews than others for a couple of reasons:

In other words, the likelihood of getting a review may not be uniform across all hosts. Yet it is another question whether this likelihood has significantly changed since the start of the pandemic. If not, then we can still use the number of reviews as a proxy for the number of bookings and examine the relative change compared to a pre-COVID period.


Exercise 4
Create a file clean.R that loads the data from the data directory and reshapes the data into the following format:

date neighbourhood num_reviews
2015-01-01 Bijlmer-Centrum 43
2015-02-01 Bijlmer-Centrum 94
â€Ĥ â€Ĥ â€Ĥ.
2020-12-01 Zuid 23

Please follow the guidelines below:


3. Output

Exercise 5
Create the following three deliverables:

  1. A pivot table that has the following format (vertical: dates, horizontal: neighbourhoods). Store it as pivot_table.csv in gen/analysis.
date Bijlmer-Centrum Bijlmer-Oost â€Ĥ Zuid
2015-01-01 â€Ĥ â€Ĥ â€Ĥ â€Ĥ
2015-02-01 â€Ĥ â€Ĥ â€Ĥ â€Ĥ
â€Ĥ â€Ĥ â€Ĥ â€Ĥ â€Ĥ
2020-12-01 â€Ĥ â€Ĥ â€Ĥ â€Ĥ


  1. A time-series plot that shows the total number of reviews over time (across all neighborhoods). Add a plot title and axes labels to make your graph easier to read. Store it as plot_all.pdf in gen/analysis.


  1. A time-series plot that shows the total number of reviews over time for the top 3 neighborhoods (De Baarsjes - Oud-West, De Pijp - Rivierenbuurt, and Centrum-West). Add a plot title and axes labels to make your graph easier to read. Store it as plot_top3.pdf in gen/analysis.

Exercise 6

[FIGURE OF MAKE WORKFLOW]

File Description Phase
download.R Downloads the data from Inside Airbnb and stores as csv format Input
clean.R Preprocesses the raw data into an aggregated format ready for analysis and visualisation Transformation
pivot_table.R XXXX Output
plot.R XXXX Output


Exercise 7

Follow-up questions:



TEMPORARY NOTES


Every month the site updates these source files according to the changes on the Airbnb website (e.g., new listings and bookings). Although only the most recent data are listed (12 December 2020 here), archived data can be accessed as well (see figure below). Depending on the city, this data may go as far as back as the year 2015.

Data

Available t = beschikbaar f = niet beschikbaar

Aantal reserveringen

LS0tCnRpdGxlOiAiRGF0YSBDaGFsbGVuZ2UgLSBXb3JrZmxvd3MiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgZGZfcHJpbnQ6IHBhZ2VkCi0tLQoKIyMjIEluc2lkZSBBaXJibmIKW0luc2lkZSBBaXJibmJdKGh0dHA6Ly9pbnNpZGVhaXJibmIuY29tL2luZGV4Lmh0bWwpIGlzIGFuIGluZGVwZW5kZW50IG9wZW4tc291cmNlIGRhdGEgdG9vbCBkZXZlbG9wZWQgYnkgY29tbXVuaXR5IGFjdGl2aXN0IE11cnJheSBDb3ggd2hvIGFpbXMgdG8gc2hlZCBsaWdodCBvbiBob3cgQWlyYm5iIGlzIGJlaW5nIHVzZWQgYW5kIGFmZmVjdGluZyBuZWlnaGJvcmhvb2RzIGluIGxhcmdlIGNpdGllcy4gVGhlIHRvb2wgcHJvdmlkZXMgYSB2aXN1YWwgb3ZlcnZpZXcgb2YgdGhlIGFtb3VudC4gYXZhaWxhYmlsaXR5LCBhbmQgc3ByZWFkIG9mIHJvb21zIGFjcm9zcyBhIGNpdHksIGFuIGFwcHJveGltYXRpb24gb2YgdGhlIG51bWJlciBvZiBib29raW5ncyBhbmQgb2NjdXBhbmN5IHJhdGUsIGFuZCB0aGUgbnVtYmVyIG9mIGxpc3RpbmdzIHBlciBob3N0LiAKCkZvciBleGFtcGxlLCBbaGVyZV0oaHR0cDovL2luc2lkZWFpcmJuYi5jb20vYW1zdGVyZGFtLykgaXMgdGhlIGRhc2hib2FyZCBmb3IgdGhlIGNpdHkgb2YgQW1zdGVyZGFtIHdoaWNoIHNob3dzIHVzIHRoYXQgNzklIG9mIHRoZSAxOSw2MTkgbGlzdGluZ3MgYXJlIGVudGlyZSBob21lcyBvZiB3aGljaCBhYm91dCBhIHF1YXJ0ZXIgaXMgYXZhaWxhYmxlIGFsbCB5ZWFyIHJvdW5kLiBNb3Jlb3ZlciwgdGhlIGFuaW1hdGlvbiBiZWxvdyBpbGx1c3RyYXRlcyBob3cgdGhlIG51bWJlciBvZiBsaXN0aW5ncyBoYXZlIGJlZW4gZ3Jvd2luZyByYXBpZGx5IHRocm91Z2hvdXQgdGhlIHllYXJzOgoKIVtdKC4vaW1hZ2VzL2FpcmJuYl9leHBhbnNpb24uZ2lmKQpcCgojIyMgUmVzZWFyY2ggUXVlc3Rpb24gIApUaGUgb3ZlcmFyY2hpbmcgcmVzZWFyY2ggcXVlc3Rpb24gdGhhdCB3ZSBhaW0gdG8gaW52ZXN0aWdhdGUgaXM6ICAgIAoqKkhvdyBkaWQgdGhlIEFpcmJuYiBtYXJrZXQgaW4gQW1zdGVyZGFtIHJlc3BvbmQgdG8gdGhlIENPVklELTE5IHBhbmRlbWljIGluIHRlcm1zIG9mIGJvb2tpbmdzIHBlciBuZWlnaGJvcmhvb2Q/KioKClRvIGdldCB0byBhbiBhbnN3ZXIsIHdlIG5lZWQgYSBtdWx0aXR1ZGUgb2YgaW5wdXQsIHRyYW5zZm9ybWF0aW9uLCBhbmQgb3V0cHV0IHN0ZXBzLiBXZSdsbCB1c2UgYG1ha2VgIHRvIGF1dG9tYXRlIG91ciB3b3JrZmxvd3MgYW5kIG1ha2UgdGhlbSByZXByb2R1Y2libGUuIEFzIGRhdGEgb24gSW5zaWRlIEFpcmJuYiBpcyB1cGRhdGVkIG1vbnRobHksIG91ciBwcm9ncmFtIHNob3VsZCBzdGlsbCB3b3JrIG9uY2UgbmV3IGRhdGEgYmVjb21lcyBhdmFpbGFibGUgb3IgaWYgd2UgY2hhbmdlIHRoZSBjaXR5LiAKCgotLS0KCiMjIyAxLiBJbnB1dAoKIyMjIyAxLjEgRGF0YSAgClRoZSBbZGF0YV0oaHR0cDovL2luc2lkZWFpcmJuYi5jb20vZ2V0LXRoZS1kYXRhLmh0bWwpIHVuZGVybHlpbmcgSW5zaWRlIEFpcmJuYiBoYXZlIGJlZW4gYW5hbHl6ZWQsIGNsZWFuc2VkLCBhbmQgYWdncmVnYXRlZCB3aGVyZSBhcHByb3ByaWF0ZSB0byBmYWNpbGl0YXRlIHB1YmxpYyBkaXNjdXNzaW9uLiBJbiB0aGlzIGRhdGEgY2hhbGxlbmdlLCB3ZSBmb2N1cyBvbiB0aGUgYGxpc3RpbmdzLmNzdmAgYW5kIGByZXZpZXdzLmNzdmAgZmlsZXMgd2hpY2ggY29udGFpbiB0aGUgZm9sbG93aW5nIGluZm9ybWF0aW9uOiAKCipMaXN0aW5ncyogIApJbmZvcm1hdGlvbiBhYm91dCB0aGUgaG9zdCwgbG9jYXRpb24sIHJvb20gdHlwZSwgcHJpY2UsIHJldmlld3MsIGFuZCBhdmFpbGFiaWxpdHkuCgoqUmV2aWV3cyogIApUaGUgbGlzdGluZyBJRCBhbmQgdGhlIGRhdGUgb2YgdGhlIHJldmlldy4gTW9yZSBkZXRhaWxzIGFib3V0IHRoZSByZXZpZXcgc3VjaCBhcyB0aGUgY29tbWVudCBhbmQgYXV0aG9yIGNhbiBiZSBgcmV2aWV3cy5jc3YuZ3ouYCBmaWxlIGJ1dCBpcyBvdXRzaWRlIHRoZSBzY29wZSBvZiB0aGlzIHR1dG9yaWFsLgoKKipFeGVyY2lzZSAxKiogICAgIApCZWZvcmUgd2UgZnVsbHkgYXV0b21hdGUgb3VyIHdvcmtmbG93cywgaXQgaXMgaW1wZXJhdGl2ZSB0byBoYXZlIGEgY2xvc2UgbG9vayBhdCB0aGUgZGF0YS4gCgoxLiBTZXQgdXAgYSBkaXJlY3Rvcnkgc3RydWN0dXJlIGluIGFjY29yZGFuY2Ugd2l0aCB0aGVzZSBbZ3VpZGVsaW5lc10oaHR0cDovL3RpbGJ1cmdzY2llbmNlaHViLmNvbS93b3JrZmxvdy9kaXJlY3Rvcmllcy8pLiBJdCBzaG91bGQgaGF2ZSBhIGBkYXRhYCwgYGdlbmAsIGFuZCBgc3JjYCBkaXJlY3RvcnkgYW5kIGEgYGRhdGEtcHJlcGFyYXRpb25gIHN1YmRpcmVjdG9yeSBpbiBgc3JjYC4KMi4gTWFudWFsbHkgZG93bmxvYWQgdGhlIG1vc3QgcmVjZW50IHZlcnNpb24gb2YgYGxpc3RpbmdzLmNzdmAgYW5kIGByZXZpZXdzLmNzdmAgbGlzdGVkIG9uIFtJbnNpZGUgQWlyYm5iXShodHRwOi8vaW5zaWRlYWlyYm5iLmNvbS9nZXQtdGhlLWRhdGEuaHRtbCkgYW5kIHN0b3JlIHRoZW0gaW4gdGhlIGBkYXRhYCBmb2xkZXIuCjMuIENyZWF0ZSBhIGRhdGEgcmVwb3J0IChsaWtlIHlvdSBkaWQgaW4gRGF0YSBDaGFsbGVuZ2UgMSkgLiAgCiAgKiBDb2RlIG5lY2Vzc2FyeSB0byByZWFkIGluIHRoZSBkYXRhIGFuZCBwZXJmb3JtIHNvbWUgYmFzaWMgY2xlYW5pbmcgc3RlcHMKICAqIEdlbmVyYXRlIGFuIG92ZXJ2aWV3IG9mIHRoZSBkYXRhIChlLmcuLCBzdW1tYXJ5IHN0YXRpc3RpY3MsIHJlcG9ydCBvbiBtaXNzaW5nbmVzcywgbnVtYmVyIG9mIG9ic2VydmF0aW9ucywgZXRjLikKICAqIEV4cGxvcmUgaW50ZXJlc3RpbmcgcmVsYXRpb25zaGlwcyBpbiB0aGUgZGF0YS4gCgpgYGB7cn0KbGlzdGluZ3MgPC0gcmVhZC5jc3YoIi4uLy4uL2RhdGEvbGlzdGluZ3MuY3N2IikKc3VtbWFyeShsaXN0aW5ncykKCnJldmlld3MgPC0gcmVhZC5jc3YoIi4uLy4uL2RhdGEvcmV2aWV3cy5jc3YiKQpzdW1tYXJ5KHJldmlld3MpCmBgYAoKXAoKKipTb2x1dGlvbnMqKiAgCkFuIGFuc3dlciB0aGF0IGluY2x1ZGVzOiAKCiogVGhlIG51bWJlciBvZiBsaXN0aW5ncyBpcyAoKy8tIDE4SykgaXMgc29tZXdoYXQgbG93ZXIgdGhhbiB0aGUgZmlndXJlIHJlcG9ydGVkIGluIHRoZSBkYXNoYm9hcmQuIAoqIE1vc3QgaG9zdHMgaGF2ZSBvbmx5IG9uZSBsaXN0aW5nIGJ1dCBzb21lIG1heSBhY2NvdW50IGZvciA4NCBsaXN0aW5ncy4KKiBTb21lIGxpc3RpbmdzIHJlY2VpdmVkIHRoZWlyIGxhc3QgcmV2aWV3IGluIDIwMTIgd2hpY2ggaW5kaWNhdGVzIHRoYXQgbm90IGFsbCBsaXN0aW5ncyBtYXkgYmUgaW4gdXNlIGFueW1vcmUgKGZvciAyMzc1IHJlY29yZHMgdGhpcyBmaWVsZCBpcyBlbXB0eSAoYE5BYCkgd2hpY2ggc3VnZ2VzdHMgdGhhdCB0aGV5IGRpZCBub3QgcmVjZWl2ZSBhIHJldmlldyBhdCBhbGwuIFRoaXMgaXMgY29uZmlybWVkIGJ5IHRoZSBudW1iZXIgb2YgcmV2aWV3cyBjb2x1bW4gKGAwYCkuKS4KKiBNb3N0IGxpc3RpbmdzIHJlY2VpdmUgbGVzcyB0aGFuIGEgcmV2aWV3IHBlciBtb250aCAobWVhbjogMC42MywgbWVkaWFuOiAwLjMwKS4KKiBUaGUgbmVpZ2hib3Job29kcyB3aXRoIHRoZSBtb3N0IGxpc3RpbmdzIGFyZSBsb2NhdGVkIGluIERlIEJhYXJzamVzIC0gT3VkLVdlc3QsIERlIFBpanAgLSBSaXZpZXJlbmJ1dXJ0LCBhbmQgQ2VudHJ1bS1XZXN0LiBUaGUgYG5laWdoYm9yaG9vZF9ncm91cGAgY29sdW1uIGRvZXMgbm90IGNvbnRhaW4gYW55IGluZm9ybWF0aW9uIGFuZCBjb3VsZCB0aGVyZWZvcmUgYmUgcmVtb3ZlZC4KKiBGb3IgaGFsZiBvZiB0aGUgbGlzdGluZ3MsIHRoZSBkYWlseSByYXRlIGZhbGxzIHNvbWV3aGVyZSBpbiBiZXR3ZWVuIOKCrDk0IGFuZCDigqwxODAgICgxc3QgYW5kIDNyZCBxdWFudGlsZSkuCiogVGhlIHJldmlld3MgZmlsZSBpbmNsdWRlcyBhbGwgaGlzdG9yaWMgcmV2aWV3cyAobm90IGp1c3QgdGhlIG5ldyBvbmVzIHNpbmNlIHRoZSBsYXN0IGRhdGEgcmVsZWFzZSkuCiogUmV2aWV3cyBhcmUgd3JpdHRlbiBiZXR3ZWVuIE1hcmNoIDIwMDkgYW5kIERlY2VtYmVyIDIwMjAuIAoqIFRoZSB0b3RhbCBudW1iZXIgb2YgcmV2aWV3cyAoKy8tIDQ1MkspIHRoYXQgYXJlIGdyb3VwZWQgYnkgbGlzdGluZyAoMTZLKS4gR2l2ZW4gdGhlIHRvdGFsIG51bWJlciBvZiBsaXN0aW5ncyBvbiBBaXJibmIsIGl0IGltcGxpZXMgdGhhdCBub3QgYWxsIGxpc3RpbmdzIGhhdmUgYmVlbiByZXZpZXdlZC4KCk5vdGUgdGhhdCB0aGUgZmlndXJlcyBhbmQgeWVhcnMgbWVudGlvbmVkIGFib3ZlIGFyZSBiYXNlZCBvbiB0aGUgZGF0YXNldCBmcm9tIERlY2VtYmVyIDIwMjAgYW5kIHRodXMgbWF5IGRldmlhdGUgZnJvbSBtb3JlIHJlY2VudCB2ZXJzaW9ucyBvZiB0aGUgZGF0YXNldC4gCgpcCgoqKkV4ZXJjaXNlIDIqKiAgIApTYXkgdGhhdCB5b3Ugd2FudCB0byBzaGFyZSB5b3VyIHdvcmsgd2l0aCBvdGhlcnMsIHlvdSBjb3VsZCBlc3NlbnRpYWxseSBnaXZlIHRoZW0gYWNjZXNzIHRvIGJvdGggdGhlIFIgZmlsZSAoYHNyY2AgZm9sZGVyKSBhbmQgdGhlIHR3byBjc3YtZmlsZXMgKGBkYXRhYCBmb2xkZXIpLiBZZXQgaWYgeW91IHdvcmsgd2l0aCBiaWcgZGF0YSBzZXRzLCB5b3UgbWF5IHJ1biBpbnRvIHByb2JsZW1zIHRoYXQgY2Fubm90IGJlIGVhc2lseSBzaGFyZWQgdGhyb3VnaCBlbWFpbCwgR2l0aHViLCBvciBHb29nbGUgRHJpdmUuIEZvciB0aGF0IHJlYXNvbiwgaXQncyByZWNvbW1lbmRlZCB0byBjcmVhdGUgYSBzY3JpcHQgdGhhdCBwdWxscyBpbiB0aGUgZGF0YSBkaXJlY3RseSBmcm9tIHRoZSBzb3VyY2UgaXRzZWxmIHdoaWNoIGlzIHdoYXQgeW91J3JlIGdvaW5nIHRvIGRvIGluIHRoaXMgZXhlcmNpc2UuCgoxLiBDcmVhdGUgYSBuZXcgZmlsZSBgZG93bmxvYWQuUmAgYW5kIHNhdmUgaXQgaW4gdGhlIGBzcmMvZGF0YS1wcmVwYXJhdGlvbmAgZm9sZGVyLgoyLiBMb29rIHVwIHRoZSBVUkwgb2YgdGhlIGRvd25sb2FkIGxpbmtzIG9mIHRoZSBtb3N0IHJlY2VudCB2ZXJzaW9uIG9mIHRoZSBgbGlzdGluZ3MuY3N2YCBhbmQgYHJldmlld3MuY3N2YCBkYXRhc2V0cy4KMy4gRG93bmxvYWQgdGhlc2UgdHdvIGZpbGVzIGZyb20gdGhlIGFmb3JlbWVudGlvbmVkIGB1cmxzYCB1c2luZyB0aGUgUiBjb2RlIGJlbG93IGFuZCBzdG9yZSB0aGVtIGluIHRoZSBgZGF0YWAgZm9sZGVyLiAgYGRlc3RmaWxlYCBpbiBgZG93bmxvYWQuZmlsZSgpYCByZWZlcnMgdG8gdGhlIChyZWxhdGl2ZSkgZmlsZXBhdGggYW5kIGZpbGVuYW1lIChlLmcuLCBgLi4vLi4vZGF0YS9saXN0aW5ncy5jc3ZgKS4KCmBgYApkb3dubG9hZC5maWxlKHVybCA9IHVybCwgZGVzdGZpbGUgPSBmaWxlbmFtZSkgCmBgYAo0LiBSdW4gdGhlIFIgc2NyaXB0IGZyb20gdGhlIGNvbW1hbmQgbGluZSBhbmQgdGVzdCB3aGV0aGVyIGl0IHdvcmtzIGFzIGV4cGVjdGVkLiBGaXJzdCwgdHlwZSBgUmAgaW4gdGhlIGNvbW1hbmQgbGluZSAoZS5nLiwgVGVybWluYWwgb24gTWFjKSBhbmQgc2VlIHdoZXRoZXIgaXQgb3BlbnMgdGhlIFIgY29tbWFuZCBsaW5lLiBJZiBub3QsIHlvdSBtYXkgbmVlZCB0byBjb25maWd1cmUgYSBwYXRoIHRvIHRoZSBSIGxpYnJhcnkgYXMgZGVzY3JpYmVkIFtoZXJlXShodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy80NDMzNjM0NS9ydW5uaW5nLXItZnJvbS1tYWMtb3N4LXRlcm1pbmFsKS4gTmV4dCwgcnVuIHRoZSBjb21tYW5kIGJlbG93IHRvIHJ1biB0aGUgZG93bmxvYWQuUiBzY3JpcHQgZnJvbSB0aGUgdGVybWluYWwuIEl0IGRvd25sb2FkcyB0aGUgZGF0YSBmcm9tIEluc2lkZSBBaXJibmIgYW5kIHN0b3JlcyBpdCBpbnRvIHRoZSBgZGF0YWAgZGlyZWN0b3J5LgoKYGBgClIgPCBkb3dubG9hZC5SIC0tc2F2ZQpgYGAKCiFbXSguL2ltYWdlcy9kb3dubG9hZF9kYXRhLmdpZil7d2lkdGg9NTAlfQoKXAoKIyMjIDIuIFRyYW5zZm9ybWF0aW9uCgpBcyB0aGUgYXV0aG9yIG9mIEluc2lkZSBBaXJibmIgbm90ZXMsIGd1ZXN0cyBtYXkgbGVhdmUgYSByZXZpZXcgYWZ0ZXIgdGhlaXIgc3RheSwgYW5kIHRoZXNlIGNhbiBiZSB1c2VkIGFzIGFuIGluZGljYXRvciBmb3IgdGhlIG51bWJlciBvZiBib29raW5ncy4gQWx0aG91Z2ggb25seSB2ZXJpZmllZCBndWVzdHMgY2FuIHJldmlldyBsaXN0aW5ncywgaXQgaXMgdW5saWtlbHkgdGhhdCBldmVyeSBndWVzdCB3aWxsIHRha2UgdGhlIHRpbWUgdG8gd3JpdGUgb25lLiBJbiByZWFsaXR5LCB0aGUgbnVtYmVyIG9mIGJvb2tpbmdzIHdpbGwgdGh1cyBleGNlZWQgdGhlIG51bWJlciBvZiByZXZpZXdzLiAKClwKCioqRXhlcmNpc2UgMyoqICAKVGhpbmsgb2Ygc2V2ZXJhbCBhcmd1bWVudHMgd2h5IHRoaXMgbWF5IG9yIG1heSBub3QgYmUgYSBwcm9ibGVtIGluIHRoZSBjb250ZXh0IG9mIG91ciByZXNlYXJjaCBxdWVzdGlvbi4gICAKCioqU29sdXRpb24qKiAgClNvbWUgaG9zdHMgd2lsbCBiZSBtb3JlIGxpa2VseSB0byBnZXQgcmV2aWV3cyB0aGFuIG90aGVycyBmb3IgYSBjb3VwbGUgb2YgcmVhc29uczoKCiogR3Vlc3Qgd2hvIGhhZCBhIGhpZ2hseSBwb3NpdGl2ZSAob3IgbmVnYXRpdmUpIGV4cGVyaWVuY2UgbWF5IGJlIG1vcmUgaW5jbGluZWQgdG8gbGVhdmUgYSByZXZpZXcgdG8gaW5mb3JtIG90aGVyIEFpcmJuYiB2aXNpdG9ycy4KKiBHdWVzdHMgbWF5IGJlIG1vcmUgbGlrZWx5IHRvIGxlYXZlIGEgcmV2aWV3IGZvciBsaXN0aW5ncyB3aXRoIG1hbnkgb3RoZXIgcmV2aWV3cy4KKiBUaGUgaG9zdHMgaGF2ZSBnaXZlbiBhIDUtc3RhciByYXRpbmcgdG8gdGhlIGd1ZXN0cyBmaXJzdCBhbmQgaG9wZSB0aGF0IHRoZXkgd2lsbCByZWNpcHJvY2F0ZS4KKiBUaGUgaG9zdHMgbWlnaHQgaGF2ZSBzcGVjaWZpY2FsbHkgYXNrZWQgZm9yIGl0LgoKSW4gb3RoZXIgd29yZHMsIHRoZSBsaWtlbGlob29kIG9mIGdldHRpbmcgYSByZXZpZXcgbWF5IG5vdCBiZSB1bmlmb3JtIGFjcm9zcyBhbGwgaG9zdHMuIFlldCBpdCBpcyBhbm90aGVyIHF1ZXN0aW9uIHdoZXRoZXIgdGhpcyBsaWtlbGlob29kIGhhcyBzaWduaWZpY2FudGx5IGNoYW5nZWQgc2luY2UgdGhlIHN0YXJ0IG9mIHRoZSBwYW5kZW1pYy4gSWYgbm90LCB0aGVuIHdlIGNhbiBzdGlsbCB1c2UgdGhlIG51bWJlciBvZiByZXZpZXdzIGFzIGEgcHJveHkgZm9yIHRoZSBudW1iZXIgb2YgYm9va2luZ3MgYW5kIGV4YW1pbmUgdGhlIHJlbGF0aXZlIGNoYW5nZSBjb21wYXJlZCB0byBhIHByZS1DT1ZJRCBwZXJpb2QuCgpcCgoqKkV4ZXJjaXNlIDQqKiAgCkNyZWF0ZSBhIGZpbGUgYGNsZWFuLlJgIHRoYXQgbG9hZHMgdGhlIGRhdGEgZnJvbSB0aGUgYGRhdGFgIGRpcmVjdG9yeSBhbmQgcmVzaGFwZXMgdGhlIGRhdGEgaW50byB0aGUgZm9sbG93aW5nIGZvcm1hdDogCgp8IGRhdGUgfCBuZWlnaGJvdXJob29kIHwgbnVtX3Jldmlld3MgfAp8IDotLS0tIHwgOi0tLS0gfCA6LS0tLSB8CnwgMjAxNS0wMS0wMSB8IEJpamxtZXItQ2VudHJ1bSB8IDQzIHwgCnwgMjAxNS0wMi0wMSB8IEJpamxtZXItQ2VudHJ1bSB8IDk0IHwgCnwgLi4uIHwgLi4uIHwgLi4uLiB8IAp8IDIwMjAtMTItMDEgfCBadWlkIHwgMjMgfCAgCgoKUGxlYXNlIGZvbGxvdyB0aGUgZ3VpZGVsaW5lcyBiZWxvdzogIAoKKiBDb252ZXJ0IHRoZSBkYXRlIGNvbHVtbiBvZiBgcmV2aWV3c2AgaW50byBkYXRlL3RpbWUgZm9ybWF0LgoqIEZpbHRlciBmb3IgYHJldmlld3NgIHB1Ymxpc2hlZCBzaW5jZSBKYW51YXJ5IDFzdCAyMDE1CiogRmlsdGVyIGZvciBgbGlzdGluZ3NgIHRoYXQgaGF2ZSByZWNlaXZlZCBhdCBsZWFzdCAxIHJldmlldy4KKiBNZXJnZSB0aGUgYHJldmlld3NgIGFuZCBgbGlzdGluZ3NgIGRhdGFmcmFtZXMgb24gYSBjb21tb24gY29sdW1uLgoqIEdyb3VwIHRoZSBudW1iZXIgb2YgcmV2aWV3cyBieSBkYXRlIGFuZCBuZWlnaGJvcmhvb2QgKGFnZ3JlZ2F0ZWQgb24gYSBtb250aGx5IGxldmVsKS4gCiogU3RvcmUgdGhlIGZpbmFsIGRhdGEgZnJhbWVzIGluIGBnZW4vZGF0YS1wcmVwYXJhdGlvbmAgYXMgYGFnZ3JlZ2F0ZWRfZGYuY3N2YAoKXAoKIyMjIDMuIE91dHB1dAoKKipFeGVyY2lzZSA1KiogICAKQ3JlYXRlIHRoZSBmb2xsb3dpbmcgdGhyZWUgZGVsaXZlcmFibGVzOiAKCjEuIEEgcGl2b3QgdGFibGUgdGhhdCBoYXMgdGhlIGZvbGxvd2luZyBmb3JtYXQgKHZlcnRpY2FsOiBkYXRlcywgaG9yaXpvbnRhbDogbmVpZ2hib3VyaG9vZHMpLiBTdG9yZSBpdCBhcyBgcGl2b3RfdGFibGUuY3N2YCBpbiBgZ2VuL2FuYWx5c2lzYC4gCgp8IGRhdGUgfCBCaWpsbWVyLUNlbnRydW0gfCBCaWpsbWVyLU9vc3QgfCAuLi4gfCBadWlkIHwgCnwgOi0tLSB8IDotLS0gfDotLS0gfDotLS0gfCA6LS0tIHwKfCAyMDE1LTAxLTAxIHwgLi4uIHwgLi4uIHwgLi4uIHwgLi4uIHwKfCAyMDE1LTAyLTAxIHwgLi4uIHwgLi4uIHwgLi4uIHwgLi4uIHwKfCAuLi4gfCAuLi4gfCAuLi4gfCAuLi4gfCAuLi4gfAp8IDIwMjAtMTItMDEgfCAuLi4gfCAuLi4gfCAuLi4gfCAuLi4gfAoKClwKCjIuIEEgdGltZS1zZXJpZXMgcGxvdCB0aGF0IHNob3dzIHRoZSB0b3RhbCBudW1iZXIgb2YgcmV2aWV3cyBvdmVyIHRpbWUgKGFjcm9zcyBhbGwgbmVpZ2hib3Job29kcykuIEFkZCBhIHBsb3QgdGl0bGUgYW5kIGF4ZXMgbGFiZWxzIHRvIG1ha2UgeW91ciBncmFwaCBlYXNpZXIgdG8gcmVhZC4gU3RvcmUgaXQgYXMgYHBsb3RfYWxsLnBkZmAgaW4gYGdlbi9hbmFseXNpc2AuCgoqIEltcG9ydCB0aGUgZGF0YSBmcm9tIGBnZW4vZGF0YS1wcmVwYXJhdGlvbi9hZ2dyZWdhdGVkX2RmLmNzdmAKKiBDb252ZXJ0IHRoZSBgZGF0ZWAgY29sdW1uIGludG8gZGF0ZSBmb3JtYXQuCiogR3JvdXAgYnkgZGF0ZSBhbmQgY2FsY3VsYXRlIHRoZSBzdW0gb2YgYWxsIHJldmlld3MgYWNyb3NzIG5laWdob3VyaG9vZHMuCiogUGxvdCB0aGUgY2hhcnQgYW5kIHN0b3JlIHRoZSB2aXN1YWxpc2F0aW9uLgoKClwKCjMuIEEgdGltZS1zZXJpZXMgcGxvdCB0aGF0IHNob3dzIHRoZSB0b3RhbCBudW1iZXIgb2YgcmV2aWV3cyBvdmVyIHRpbWUgZm9yIHRoZSB0b3AgMyBuZWlnaGJvcmhvb2RzIChEZSBCYWFyc2plcyAtIE91ZC1XZXN0LCBEZSBQaWpwIC0gUml2aWVyZW5idXVydCwgYW5kIENlbnRydW0tV2VzdCkuIEFkZCBhIHBsb3QgdGl0bGUgYW5kIGF4ZXMgbGFiZWxzIHRvIG1ha2UgeW91ciBncmFwaCBlYXNpZXIgdG8gcmVhZC4gU3RvcmUgaXQgYXMgYHBsb3RfdG9wMy5wZGZgIGluIGBnZW4vYW5hbHlzaXNgLgoKKiBJbXBvcnQgdGhlIGRhdGEgZnJvbSBgZ2VuL2RhdGEtYW5hbHlzaXMvcGl2b3RfdGFibGUuY3N2YAoqIENvbnZlcnQgdGhlIGBkYXRlYCBjb2x1bW4gaW50byBkYXRlIGZvcm1hdC4KKiBQbG90IHRoZSBjaGFydCBhbmQgc3RvcmUgdGhlIHZpc3VhbGlzYXRpb24uCgoKKipFeGVyY2lzZSA2KiogIAoKKiBDcmVhdGUgd29ya2Zsb3cgb3Agb3JkZSBtYWtlbgoqIEFtc3RlcmRhbSBmaWxlIHN3YXBwZW4gdm9vciBiaWp2LiBOZXcgWW9yayBVUkxzIGVuIGRhbiBub2dtYWFscyBgbWFrZWAgcnVubmVuCiogVnJhYWcgb3ZlciBkZXBlbmRlbmNpZXMgYmlubmVuIE1ha2UgCgpbRklHVVJFIE9GIE1BS0UgV09SS0ZMT1ddCgoKfCBGaWxlIHwgRGVzY3JpcHRpb24gfCBQaGFzZSB8IAp8IC0tLS0gfCAtLS0tLS0tLS0tIHwgLS0tLS0tIHwgCnwgYGRvd25sb2FkLlJgIHwgRG93bmxvYWRzIHRoZSBkYXRhIGZyb20gSW5zaWRlIEFpcmJuYiBhbmQgc3RvcmVzIGFzIGNzdiBmb3JtYXQgfCBJbnB1dCB8IAp8IGBjbGVhbi5SYCB8IFByZXByb2Nlc3NlcyB0aGUgcmF3IGRhdGEgaW50byBhbiBhZ2dyZWdhdGVkIGZvcm1hdCByZWFkeSBmb3IgYW5hbHlzaXMgYW5kIHZpc3VhbGlzYXRpb24gIHwgVHJhbnNmb3JtYXRpb24gfCAKfCBgcGl2b3RfdGFibGUuUmAgfCBYWFhYIHwgT3V0cHV0IHwgCnwgYHBsb3QuUmAgfCBYWFhYIHwgT3V0cHV0IHwgCgpcCgoqKkV4ZXJjaXNlIDcqKiAgCgoqIFdhYXJvbSBpcyBEZWNlbWJlciAyMDIwIGxhZ2VyIGRhbiB2ZXJ3YWNodCBrYW4gd29yZGVuPyAobmlldCBlZW4gdm9sbGVkaWdlIG1hYW5kKQoKKiBSZWdyZXNzaWUgY29lZmZpY2llbnRlbiBpbnRlcnByZXRlcmVuIGVuIG9uZGVyem9la3N2cmFhZyBiZWFudHdvb3JkZW4KKiBWZXJnZWxpamtpbmcgdHVzc2VuIGRlIHZlcnNjaGlsbGVuZGUgbmVpZ2hib3Job29kcwoqIEtvcnQgaW5nYWFuIG9wIGxpbWl0YXRpZXMgdmFuIHN0dWRpZQoKCgoKRm9sbG93LXVwIHF1ZXN0aW9uczogCgoKKiBTaW1wbGUgbGFnZ2VkIHRpbWVzZXJpZXMgbW9kZWwKICAqIEJvb2tpbmdzID0gYm9va2luZ3MgMTIgbW9udGhzIGFnbyArIC4uICsgcHJpY2UgKyByb29tIHR5cGUgZHVtbXkgKyBDT1ZJRCBkdW1teQogICogRXhwb3J0IHJlc3VsdHMgd2l0aCBzdGFyZ2F6ZXIgbGlicmFyeSAobGluayB0byBidWlsZGluZyBibG9jaykKKiBBcHByb3hpbWF0ZSBlc3RpbWF0ZWQgaW5jb21lIC8gbW9udGgKKiBEbyBob3N0cyBzdGljayB0byB0aGUgcmVudGFsIHBvbGljeSBpbXBvc2VkIGJ5IHRoZSBjaXR5IG9mIEFtc3RlcmRhbSAoMzAgZGF5cyAvIHllYXIgbWF4Lik/CgoKCgpcCgpcCgoKIyMjIFRFTVBPUkFSWSBOT1RFUwoKLS0tCgoKCgoKRXZlcnkgbW9udGggdGhlIHNpdGUgdXBkYXRlcyB0aGVzZSBzb3VyY2UgZmlsZXMgYWNjb3JkaW5nIHRvIHRoZSBjaGFuZ2VzIG9uIHRoZSBBaXJibmIgd2Vic2l0ZSAoZS5nLiwgbmV3IGxpc3RpbmdzIGFuZCBib29raW5ncykuIEFsdGhvdWdoIG9ubHkgdGhlIG1vc3QgcmVjZW50IGRhdGEgYXJlIGxpc3RlZCAoMTIgRGVjZW1iZXIgMjAyMCBoZXJlKSwgYXJjaGl2ZWQgZGF0YSBjYW4gYmUgYWNjZXNzZWQgYXMgd2VsbCAoc2VlIGZpZ3VyZSBiZWxvdykuIERlcGVuZGluZyBvbiB0aGUgY2l0eSwgdGhpcyBkYXRhIG1heSBnbyBhcyBmYXIgYXMgYmFjayBhcyB0aGUgeWVhciAyMDE1LgoKIVtdKC4vaW1hZ2VzL2FyY2hpdmVkX2RhdGEucG5nKQoKCgoKCgoKKipEYXRhKiogIAoKKiBOb2VtZW4gZGF0IGplIGRlIGRhdGEgbmlldCBpbiBFeGNlbCBrYW4gb3BlbmVuIChjYXBwZWQgYXQgMS4wNE0gcm93cykKKiB2b29yIGVsa2UgbGlzdGluZyAzNjUgY2FsZW5kYXIgZGF0YSBwb2ludHMKICAqIEJpanYuIDEyLTEyLTIwMjAgLT4gMTMtMTItMjAyMCB0b3QgZW4gbWV0IDE0LTEyLTIwMjE7CiAgKiBrdW4gamUgemVsZiBvb2sgcHJvYmVyZW4gKGplIGt1bnQgbmlldCB2ZXJkZXIgdGVydWdzY3JvbGxlbiBpbiBkZSBrYWxlbmRlciBvcCBBaXJibmIpCiAgKiBkYXRhLWlzLWRheS1ibG9ja2VkIGF0dHJpYnV0ZSAod2ViIHNjcmFwaW5nIHJlZikKCkF2YWlsYWJsZQp0ID0gYmVzY2hpa2JhYXIKZiA9IG5pZXQgYmVzY2hpa2JhYXIKCioqQWFudGFsIHJlc2VydmVyaW5nZW4qKgoKKiBBbHMgZGUgKGthbWVyLCBkYXR1bSkgY29tYmluYXRpZSBlZW4ga2VlciAidCIgaXMgZ2V3ZWVzdCBlbiBpbiBoZXQgdmVydm9sZyAiZiIgaXMgZGF0IGJlc2Nob3V3ZW4gYWxzIGVlbiByZXNlcnZlcmluZyAtPiAod29yZHQgdGUgaW5nZXdpa2tlbGQhISEpCiogQWFubmVtZW4gZGF0IGllZGVyZWVuIHppam4gY2FsZW5kYXIgY29uc2VxdWVudCBiaWpob3VkdCBlbiB2b29yIGZhbHNlIGtpZXN0IGFscyB6ZSBvb2sgbmlldCB3aWxsZW4gdmVyaHVyZW4gLT4gYmxpamt0IGdlZW4gZ29lZGUgYWFubmFtZSAKKiBMaW5rIHRvIHJlY2VudCBuZXdzIGFydGljbGVzCiAgKiBodHRwczovL25vcy5ubC9hcnRpa2VsLzIzMjgxODEtd29uaW5nLXZpYS1haXJibmItdmVyaHVyZW4taW4tZGVuLWhhYWctdmVyYm9kZW4tZ2VtZWVudGUtZ2FhdC1iZWJvZXRlbi5odG1sCiAgKiBodHRwczovL3d3dy5ydGxuaWV1d3MubmwvbmlldXdzL25lZGVybGFuZC9hcnRpa2VsLzUxODQ4MDgvYWlyYm5iLXJlY2h0c3pha2VuLXR1aW5odWlzLWJlbGFzdGluZ2RpZW5zdAoKKiBtYXggMzAgZGFnZW4gKGJpanYuIGFscyBqZSB6ZWxmIG9wIHZha2FudGllIGdhYXQpCiogd29uaW5nZW4gbW9nZW4gbmlldCBzdHJ1Y3R1cmVlbCB3b3JkZW4gb250dHJva2tlbgoKCg==